const { pool, query: dbQuery } = require('../config/database');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const { logger } = require('../utils/logger');

/**
 * 用户数据模型
 * 处理用户相关的数据库操作
 */
class User {
  constructor(userData) {
    this.user_id = userData.user_id;
    this.username = userData.username;
    this.email = userData.email;
    this.phone = userData.phone;
    this.password_hash = userData.password_hash;
    this.first_name = userData.first_name;
    this.last_name = userData.last_name;
    this.date_of_birth = userData.date_of_birth;
    this.gender = userData.gender;
    this.profile_image_url = userData.profile_image_url;
    this.membership_level = userData.membership_level || 'bronze';
    this.points_balance = userData.points_balance || 0;
    this.total_spent = userData.total_spent || 0.00;
    this.preferred_language = userData.preferred_language || 'zh';
    this.email_verified = userData.email_verified || false;
    this.phone_verified = userData.phone_verified || false;
    this.is_active = userData.is_active !== undefined ? userData.is_active : true;
    this.last_login_at = userData.last_login_at;
    this.created_at = userData.created_at;
    this.updated_at = userData.updated_at;
  }

  /**
   * 创建新用户
   * @param {Object} userData - 用户数据
   * @returns {Promise<Object>} 创建的用户信息
   */
  static async create(userData) {
    try {
      // 验证必填字段
      if (!userData.email || !userData.password) {
        throw new Error('邮箱和密码是必填字段');
      }

      // 检查邮箱是否已存在
      const existingUser = await User.findByEmail(userData.email);
      if (existingUser) {
        throw new Error('该邮箱已被注册');
      }

      // 如果提供了手机号，检查是否已存在
      if (userData.phone) {
        const existingPhone = await User.findByPhone(userData.phone);
        if (existingPhone) {
          throw new Error('该手机号已被注册');
        }
      }

      // 加密密码
      const saltRounds = 12;
      const passwordHash = await bcrypt.hash(userData.password, saltRounds);

      // 生成用户名（如果未提供）
      const username = userData.username || `user_${Date.now()}`;

      const sql = 'INSERT INTO users (username, email, phone, password_hash, first_name, last_name, date_of_birth, gender, preferred_language, membership_level, points_balance, total_spent, is_active, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())';

      const values = [
        username,
        userData.email,
        userData.phone || null,
        passwordHash,
        userData.first_name || null,
        userData.last_name || null,
        userData.date_of_birth || null,
        userData.gender || null,
        userData.preferred_language || 'zh',
        'bronze', // 默认会员等级
        0, // 初始积分
        0.00, // 初始消费金额
        true // 默认激活状态
      ];

      logger.debug('About to execute dbQuery with sql:', sql);
      logger.debug('Values:', values);
      const result = await dbQuery(sql, values);
      logger.debug('dbQuery result:', result);
      logger.debug('result type:', typeof result);
      logger.debug('result keys:', Object.keys(result || {}));
      
      // 检查result是否有效
      if (!result || typeof result.insertId === 'undefined') {
        logger.error('数据库插入失败，未返回有效的insertId');
        throw new Error('用户创建失败：数据库插入异常');
      }
      
      const userId = result.insertId;

      // 返回创建的用户信息（不包含密码）
      const newUser = await User.findById(userId);
      return newUser;
    } catch (error) {
      logger.error('创建用户失败:', error);
      throw error;
    }
  }

  /**
   * 根据ID查找用户
   * @param {number} userId - 用户ID
   * @returns {Promise<Object|null>} 用户信息
   */
  static async findById(userId) {
    try {
      const sql = `
        SELECT user_id, username, email, phone, first_name, last_name,
               date_of_birth, gender, profile_image_url, membership_level,
               points_balance, total_spent, preferred_language,
               email_verified, phone_verified, is_active,
               last_login_at, created_at, updated_at
        FROM users
        WHERE user_id = ? AND is_active = true
      `;
      
      const rows = await dbQuery(sql, [userId]);
      return rows.length > 0 ? new User(rows[0]) : null;
    } catch (error) {
      logger.error('查找用户失败:', error);
      throw error;
    }
  }

  /**
   * 根据邮箱查找用户
   * @param {string} email - 邮箱地址
   * @returns {Promise<Object|null>} 用户信息
   */
  static async findByEmail(email) {
    try {
      const sql = `
        SELECT user_id, username, email, phone, password_hash, first_name, last_name,
               date_of_birth, gender, profile_image_url, membership_level,
               points_balance, total_spent, preferred_language,
               email_verified, phone_verified, is_active,
               last_login_at, created_at, updated_at
        FROM users
        WHERE email = ? AND is_active = true
      `;
      
      const rows = await dbQuery(sql, [email]);
      return rows.length > 0 ? new User(rows[0]) : null;
    } catch (error) {
      logger.error('根据邮箱查找用户失败:', error);
      throw error;
    }
  }

  /**
   * 根据手机号查找用户
   * @param {string} phone - 手机号
   * @returns {Promise<Object|null>} 用户信息
   */
  static async findByPhone(phone) {
    try {
      const sql = `
        SELECT user_id, username, email, phone, password_hash, first_name, last_name,
               date_of_birth, gender, profile_image_url, membership_level,
               points_balance, total_spent, preferred_language,
               email_verified, phone_verified, is_active,
               last_login_at, created_at, updated_at
        FROM users
        WHERE phone = ? AND is_active = true
      `;
      
      const rows = await dbQuery(sql, [phone]);
      return rows.length > 0 ? new User(rows[0]) : null;
    } catch (error) {
      logger.error('根据手机号查找用户失败:', error);
      throw error;
    }
  }

  /**
   * 验证用户密码
   * @param {string} password - 明文密码
   * @returns {Promise<boolean>} 验证结果
   */
  async validatePassword(password) {
    try {
      const hash = this.password_hash || '';
      const looksBcryptHash = typeof hash === 'string' && hash.startsWith('$2');

      // 如果是bcrypt哈希，走正常校验
      if (looksBcryptHash) {
        return await bcrypt.compare(password, hash);
      }

      // 在使用模拟数据库或开发环境未配置真实DB时，mock数据中存的是明文口令，做安全受限的直接比较
      const usingMock = process.env.USE_MOCK_DB === 'true' || ((!process.env.NODE_ENV || process.env.NODE_ENV === 'development') && !process.env.DB_PASSWORD);
      if (usingMock) {
        return password === hash;
      }

      // 既不是bcrypt哈希也不在mock环境，为了安全返回false
      return false;
    } catch (error) {
      logger.error('密码验证失败:', error);
      return false;
    }
  }

  /**
   * 生成JWT令牌
   * @returns {string} JWT令牌
   */
  generateToken() {
    const payload = {
      userId: this.user_id,
      email: this.email,
      membershipLevel: this.membership_level
    };

    return jwt.sign(
      payload,
      process.env.JWT_SECRET,
      { 
        expiresIn: process.env.JWT_EXPIRES_IN || '7d',
        issuer: 'cu-mr-bull-api'
      }
    );
  }

  /**
   * 更新最后登录时间
   * @returns {Promise<boolean>} 更新结果
   */
  async updateLastLogin() {
    try {
      const sql = 'UPDATE users SET last_login_at = NOW() WHERE user_id = ?';
      await dbQuery(sql, [this.user_id]);
      return true;
    } catch (error) {
      logger.error('更新最后登录时间失败:', error);
      return false;
    }
  }

  /**
   * 更新用户信息
   * @param {Object} updateData - 要更新的数据
   * @returns {Promise<Object>} 更新后的用户信息
   */
  async update(updateData) {
    try {
      const allowedFields = [
        'username', 'first_name', 'last_name', 'date_of_birth',
        'gender', 'profile_image_url', 'preferred_language'
      ];

      const updateFields = [];
      const values = [];

      // 只更新允许的字段
      for (const field of allowedFields) {
        if (updateData[field] !== undefined) {
          updateFields.push(`${field} = ?`);
          values.push(updateData[field]);
        }
      }

      if (updateFields.length === 0) {
        throw new Error('没有可更新的字段');
      }

      updateFields.push('updated_at = NOW()');
      values.push(this.user_id);

      const sql = `UPDATE users SET ${updateFields.join(', ')} WHERE user_id = ?`;
      await dbQuery(sql, values);

      // 返回更新后的用户信息
      return await User.findById(this.user_id);
    } catch (error) {
      logger.error('更新用户信息失败:', error);
      throw error;
    }
  }

  /**
   * 更新密码
   * @param {string} newPassword - 新密码
   * @returns {Promise<boolean>} 更新结果
   */
  async updatePassword(newPassword) {
    try {
      const saltRounds = 12;
      const passwordHash = await bcrypt.hash(newPassword, saltRounds);
      
      const sql = 'UPDATE users SET password_hash = ?, updated_at = NOW() WHERE user_id = ?';
      await dbQuery(sql, [passwordHash, this.user_id]);
      
      return true;
    } catch (error) {
      logger.error('更新密码失败:', error);
      return false;
    }
  }

  /**
   * 验证邮箱
   * @returns {Promise<boolean>} 验证结果
   */
  async verifyEmail() {
    try {
      const sql = 'UPDATE users SET email_verified = true, updated_at = NOW() WHERE user_id = ?';
      await dbQuery(sql, [this.user_id]);
      this.email_verified = true;
      return true;
    } catch (error) {
      logger.error('验证邮箱失败:', error);
      return false;
    }
  }

  /**
   * 验证手机号
   * @returns {Promise<boolean>} 验证结果
   */
  async verifyPhone() {
    try {
      const sql = 'UPDATE users SET phone_verified = true, updated_at = NOW() WHERE user_id = ?';
      await dbQuery(sql, [this.user_id]);
      this.phone_verified = true;
      return true;
    } catch (error) {
      logger.error('验证手机号失败:', error);
      return false;
    }
  }

  /**
   * 增加积分
   * @param {number} points - 要增加的积分
   * @param {string} reason - 积分变动原因
   * @returns {Promise<boolean>} 操作结果
   */
  async addPoints(points, reason = '系统奖励') {
    try {
      await db.beginTransaction();

      // 更新用户积分
      const updateSql = 'UPDATE users SET points_balance = points_balance + ?, updated_at = NOW() WHERE user_id = ?';
      await dbQuery(updateSql, [points, this.user_id]);

      // 记录积分变动历史（如果有积分历史表的话）
      // 这里可以扩展积分历史记录功能

      await db.commit();
      this.points_balance += points;
      return true;
    } catch (error) {
      await db.rollback();
      logger.error('增加积分失败:', error);
      return false;
    }
  }

  /**
   * 获取用户的安全信息（不包含敏感数据）
   * @returns {Object} 安全的用户信息
   */
  toSafeObject() {
    return {
      user_id: this.user_id,
      username: this.username,
      email: this.email,
      phone: this.phone,
      first_name: this.first_name,
      last_name: this.last_name,
      date_of_birth: this.date_of_birth,
      gender: this.gender,
      profile_image_url: this.profile_image_url,
      membership_level: this.membership_level,
      points_balance: this.points_balance,
      total_spent: this.total_spent,
      preferred_language: this.preferred_language,
      email_verified: this.email_verified,
      phone_verified: this.phone_verified,
      last_login_at: this.last_login_at,
      created_at: this.created_at,
      updated_at: this.updated_at
    };
  }

  /**
   * 软删除用户（设置为非活跃状态）
   * @returns {Promise<boolean>} 删除结果
   */
  async softDelete() {
    try {
      const sql = 'UPDATE users SET is_active = false, updated_at = NOW() WHERE user_id = ?';
      await dbQuery(sql, [this.user_id]);
      this.is_active = false;
      return true;
    } catch (error) {
      logger.error('软删除用户失败:', error);
      return false;
    }
  }

  static async count() {
    try {
      const rows = await dbQuery('SELECT COUNT(*) AS total FROM users');
      const r = Array.isArray(rows) ? rows[0] : rows;
      return (r && (r.total ?? r.count)) || 0;
    } catch (error) {
      logger.error('用户计数失败:', error);
      return 0;
    }
  }
}

module.exports = User;